import axios from 'axios';
import axiosRetry from 'axios-retry';

import Config from '../../config';
import Web3Manager from '../../libs/web3-manager';
import AuthenticationManager from '../authentication/authentication-manager';
import Disbursement from '../disbursement/disbursement';
import Transaction from './transaction';

axiosRetry(axios, {
    retries: 3,
    retryDelay: (retryCount) => {
        return retryCount * 1000;
    },
});

export default class TransactionManager {
    static save = async (
        disbursementID: number,
        transactions: Array<Transaction>
    ): Promise<Disbursement> => {
        try {
            const data = {
                disbursement_id: disbursementID,
            };

            data['transactions'] = [];

            for (let i = 0; i < transactions.length; i++) {
                const transaction = transactions[i];
                data['transactions'].push({
                    csv_line: transaction.csvLine,
                    name: transaction.name,
                    amount: transaction.amount,
                    wallet_address: transaction.walletAddress,
                    email: transaction.email,
                    member_id : transaction.memberID
                });
            }

            const call = await axios.post(Config.getAPI() + '/transaction/save', data, {
                headers: {
                    [AuthenticationManager.KEY]: AuthenticationManager.getKey(),
                    [AuthenticationManager.SECRET]: AuthenticationManager.getSecret(),
                    wallet_address: await Web3Manager.getWalletAddress(),
                },
            });

            if (call.data['disbursement']) {
                return Disbursement.fromJSON(call.data['disbursement']);
            }
        } catch (exception) {
            console.log(exception);
        }

        return null;
    };

    static getByPage = async (
        disbursementID: number,
        page = 0
    ): Promise<{ list: Array<Transaction>; hasMore: boolean; disbursement: {} }> => {
        const call = await axios.get(
            Config.getAPI() + `/transaction/all?disbursement_id=${disbursementID}&page=${page}`,
            {
                headers: {
                    [AuthenticationManager.KEY]: AuthenticationManager.getKey(),
                    [AuthenticationManager.SECRET]: AuthenticationManager.getSecret(),
                    wallet_address: await Web3Manager.getWalletAddress(),
                },
            }
        );

        if (call.data?.error) {
            throw call.data.error;
        }

        const result = {
            disbursement: {},
            list: [],
            hasMore: false,
        };

        if (call.data && call.data.transactions) {
            const { disbursement, transactions } = call.data;

            result.disbursement = disbursement;

            for (const item of transactions) {
                const { transaction, gas_fee } = item;

                const tmp = new Transaction();

                tmp.id = transaction.id;
                tmp.name = transaction.name;
                tmp.walletAddress = transaction['wallet_address'];
                tmp.amount = transaction.amount;
                tmp.currency = transaction.currency;
                tmp.email = transaction.email;
                tmp.status = transaction.status;
                tmp.errorMessage = transaction['error_message'];
                tmp.transactionHash = transaction.transaction_hash;
                tmp.timestamp = transaction.timestamp;
                tmp.gasFee = gas_fee ? gas_fee : { amount: 0, token: '' };
                result.list.push(tmp);
            }

            result.hasMore = !call.data.no_more_results;
        }

        return result;
    };

    static getAll = async (
        disbursementID: number,
        page?: number,
        curr = []
    ): Promise<Transaction[]> => {
        if (!page) {
            page = 0;
        }

        try {
            const { list, hasMore } = await TransactionManager.getByPage(disbursementID, page);

            curr = [...curr, ...list];
            if (hasMore) {
                curr = await TransactionManager.getAll(disbursementID, page + 1, curr);
            }
        } catch (exception) {
            console.log(exception);
        }

        return curr;
    };
}
